<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>!! Vector Formula !!</title>
<script type="text/javascript" src="wz_jsgraphics.js"></script>
</head>
<body onkeypress="move_formula(event.which)">
<div id="myCanvas" style="position:relative; height: 700px; width: 100%; background-color:gray"></div>
<script type="text/javascript">
var jg = new jsGraphics(document.getElementById("myCanvas"));
var speedX = 0;
var speedY = 0;
var locationX = 50;
var locationY = 50;
var prevLocationX;
var prevLocationY;
var originalButtonColor = 0;
var innerX = new Array();
var innerY = new Array();
var outerX = new Array();
var outerY = new Array();
var collision = false;

function draw()
{
	var alpha = 0;
	var tmpX = 0;
	var tmpY = 0;
	var size = Math.sqrt(speedX*speedX+speedY*speedY) * 0.2;
	jg.setColor("#ff0000");
	jg.drawLine(prevLocationX, prevLocationY, locationX, locationY);
	alpha = Math.atan2(speedY, speedX);
	tmpX = Math.cos(alpha)*-size - Math.sin(alpha)*-size;
	tmpY = Math.sin(alpha)*-size + Math.cos(alpha)*-size;
	jg.drawLine(locationX, locationY, locationX + tmpX, locationY + tmpY);
	tmpX = Math.cos(alpha)*-size - Math.sin(alpha)*size;
	tmpY = Math.sin(alpha)*-size + Math.cos(alpha)*size;
	jg.drawLine(locationX, locationY, locationX + tmpX, locationY + tmpY);
	jg.paint();
}

function checkCollision()
{
	collision = false;

	var a1y = prevLocationY;
	var a1x = prevLocationX;
	var a2y = locationY;
	var a2x = locationX;
	var ak = (a2y - a1y) / (a2x - a1x);
	var i = 0;

	var maxX = Math.max(a1x, a2x);
	var minX = Math.min(a1x, a2x);
	var maxY = Math.max(a1y, a2y);
	var minY = Math.min(a1y, a2y);

	var b1y;
	var b1x;
	var b2y;
	var b2x;
	var bk;

	var X;
	var Y;

	var maxXB;
	var minXB;
	var maxYB;
	var minYB;

	//check track's outer bounds
	for (i = 0; i < outerX.length - 1; i++)
	{	
		b1y = outerY[i] + 400;
		b1x = outerX[i] + 400;
		b2y = outerY[i+1] + 400;
		b2x = outerX[i+1] + 400;
		bk = (b2y - b1y) / (b2x - b1x);

		X = (b1y - bk*b1x - a1y + ak*a1x) / (ak - bk);
		Y = ak*(X-a1x) + a1y;

		maxXB = Math.max(b1x, b2x);
		minXB = Math.min(b1x, b2x);
		maxYB = Math.max(b1y, b2y);
		minYB = Math.min(b1y, b2y);

		if (X >= minX && X <= maxX && Y >= minY && Y <= maxY)
		{
			if (X >= minXB && X <= maxXB && Y >= minYB && Y <= maxYB)
			{
				collision = true;
				return collision;
			}
		}
	}

	//check the last vector
	b1y = outerY[outerY.length - 1] + 400;
	b1x = outerX[outerX.length - 1] + 400;
	b2y = outerY[0] + 400;
	b2x = outerX[0] + 400;
	bk = (b2y - b1y) / (b2x - b1x);

	X = (b1y - bk*b1x - a1y + ak*a1x) / (ak - bk);
	Y = ak*(X-a1x) + a1y;

	maxXB = Math.max(b1x, b2x);
	minXB = Math.min(b1x, b2x);
	maxYB = Math.max(b1y, b2y);
	minYB = Math.min(b1y, b2y);

	if (X >= minX && X <= maxX && Y >= minY && Y <= maxY)
	{
		if (X >= minXB && X <= maxXB && Y >= minYB && Y <= maxYB)
		{
			collision = true;
			return collision;
		}
	}


	//check track's inner bounds
	for (i = 0; i < innerX.length - 1; i++)
	{	
		b1y = innerY[i] + 400;
		b1x = innerX[i] + 400;
		b2y = innerY[i+1] + 400;
		b2x = innerX[i+1] + 400;
		bk = (b2y - b1y) / (b2x - b1x);

		X = (b1y - bk*b1x - a1y + ak*a1x) / (ak - bk);
		Y = ak*(X-a1x) + a1y;

		maxXB = Math.max(b1x, b2x);
		minXB = Math.min(b1x, b2x);
		maxYB = Math.max(b1y, b2y);
		minYB = Math.min(b1y, b2y);

		if (X >= minX && X <= maxX && Y >= minY && Y <= maxY)
		{
			if (X >= minXB && X <= maxXB && Y >= minYB && Y <= maxYB)
			{
				collision = true;
				return collision;
			}
		}
	}

	//check the last vector
	b1y = innerY[innerY.length - 1] + 400;
	b1x = innerX[innerX.length - 1] + 400;
	b2y = innerY[0] + 400;
	b2x = innerX[0] + 400;
	bk = (b2y - b1y) / (b2x - b1x);

	X = (b1y - bk*b1x - a1y + ak*a1x) / (ak - bk);
	Y = ak*(X-a1x) + a1y;

	maxXB = Math.max(b1x, b2x);
	minXB = Math.min(b1x, b2x);
	maxYB = Math.max(b1y, b2y);
	minYB = Math.min(b1y, b2y);

	if (X >= minX && X <= maxX && Y >= minY && Y <= maxY)
	{
		if (X >= minXB && X <= maxXB && Y >= minYB && Y <= maxYB)
		{
			collision = true;
			return collision;
		}
	}
	return collision;
}

function clearScreen()
{
	jg.clear();
}

function drawTrack(steps, innerRadius, outerRadius)
{
	var angle;
	var innerRandom = Math.floor(Math.random()*innerRadius);
	var outerRandom = innerRadius + Math.floor(Math.random()*outerRadius);
	var innerPoints = new Array();
	var outerPoints = new Array();
	var angles = new Array();

	angle = 360 / steps;
	for (var i = 0; i < steps; i++)
	{
		outerPoints[i] = innerRadius + 10 + 20 + Math.floor(Math.random()*outerRadius);	
		innerPoints[i] = 20 + Math.floor(Math.random()*innerRadius);
		angles[i] = i*angle + Math.floor(Math.random()*angle);
		
		innerX[i] = innerPoints[i]*Math.cos(angles[i]*Math.PI/180);
		innerY[i] = innerPoints[i]*Math.sin(angles[i]*Math.PI/180);
		outerX[i] = outerPoints[i]*Math.cos(angles[i]*Math.PI/180);
		outerY[i] = outerPoints[i]*Math.sin(angles[i]*Math.PI/180);
	}

	jg.clear(); //clear the screen
	jg.setColor("#000000");
	for (var i = 0; i < steps - 1; i++)
	{
		jg.drawLine(innerX[i] + 400, innerY[i] + 400, innerX[i+1] + 400, innerY[i+1] + 400);
		jg.drawLine(outerX[i] + 400, outerY[i] + 400, outerX[i+1] + 400, outerY[i+1] + 400);
		jg.paint();
		//jg.drawLine(innerX[i] + 400 + 100*Math.cos(i*angle*Math.PI/180), innerY[i] + 400, innerX[i+1] + 400 + 100*Math.cos((i+1)*angle*Math.PI/180), innerY[i+1] + 400);
		//jg.drawLine(outerX[i] + 400 + 100*Math.cos(i*angle*Math.PI/180), outerY[i] + 300, outerX[i+1] + 400 + 100*Math.cos((i+1)*angle*Math.PI/180), outerY[i+1] + 300);
	}
	jg.drawLine(innerX[innerX.length - 1] + 400, innerY[innerY.length - 1] + 400, innerX[0] + 400, innerY[0] + 400);
	jg.drawLine(outerX[outerX.length - 1] + 400, outerY[outerY.length - 1] + 400, outerX[0] + 400, outerY[0] + 400);
	jg.setColor("#00ff00");
	jg.drawLine(innerX[0] + 400, innerY[0] + 400, outerX[0] + 400, outerY[0] + 400); //draw finish line
	locationX = 400 + innerX[0] + (outerX[0] - innerX[0])/2;
	locationY = 400 + innerY[0] + (outerY[0] - innerY[0])/2;
	speedX = 0;
	speedY = 0;
	jg.paint();
}

function highlight(button)
{
	var obj;
	if (originalButtonColor == 0)
	{	
		originalButtonColor = document.getElementById("sw").style.backgroundColor;
	}
	switch (button)
	{
		case 1:
			obj = document.getElementById("sw");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 2:
			obj = document.getElementById("s");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 3:
			obj = document.getElementById("se");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 4:
			obj = document.getElementById("w");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 5:
			obj = document.getElementById("zero");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 6:
			obj = document.getElementById("e");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 7:
			obj = document.getElementById("nw");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 8:
			obj = document.getElementById("n");
			obj.style.backgroundColor = "#ff0000";
			break;

		case 9:
			obj = document.getElementById("ne");
			obj.style.backgroundColor = "#ff0000";
			break;


		default:
			break;
	}
}

function dehighlight(button)
{
	var obj;
	switch (button)
	{
		case 1:
			obj = document.getElementById("sw");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 2:
			obj = document.getElementById("s");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 3:
			obj = document.getElementById("se");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 4:
			obj = document.getElementById("w");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 5:
			obj = document.getElementById("zero");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 6:
			obj = document.getElementById("e");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 7:
			obj = document.getElementById("nw");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 8:
			obj = document.getElementById("n");
			obj.style.backgroundColor = originalButtonColor;
			break;

		case 9:
			obj = document.getElementById("ne");
			obj.style.backgroundColor = originalButtonColor;
			break;

		default:
			break;
	}
}

function drive(button)
{
	switch (button)
	{
		case 1:
			speedX = speedX - 5;
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 2:
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 3:
			speedX = speedX + 5;
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			raw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 4:
			speedX = speedX - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 5:
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 6:
			speedX = speedX + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 7:
			speedX = speedX - 5;
			speedY = speedY - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 8:
			speedY = speedY - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		case 9:
			speedX = speedX + 5;
			speedY = speedY - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;

		default:
			break;
	}
}

function move_formula(key)
{
	//ie doesn't support event.which, it handles event.keyCode
	if (!key)
	{
		key = event.keyCode;
	}

	switch (key)
	{

		case 122:
		case 49:
			speedX = speedX - 5;
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 120:
		case 50:
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 99:
		case 51:
			speedX = speedX + 5;
			speedY = speedY + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 97:
		case 52:
			speedX = speedX - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 115:
		case 53:
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 100:
		case 54:
			speedX = speedX + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 113:
		case 55:
			speedX = speedX - 5;
			speedY = speedY - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 119:
		case 56:
			speedY = speedY - 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		case 101:
		case 57:
			speedY = speedY - 5;
			speedX = speedX + 5;
			prevLocationX = locationX;
			prevLocationY = locationY;
			locationX = locationX + speedX;
			locationY = locationY + speedY;
			draw();
			if (checkCollision() == true)
			{
				alert("BOOOM!");
			}
			break;
		default:
			break;

	}
}

</script>
<table style="text-align: center">
<tr>
<td> 
<input type="button" id="nw" value="NW" style="width: 30px; height: 30px" onclick="drive(7)" onmouseover="highlight(7)" onmouseout="dehighlight(7)" />
</td>
<td>
<input type="button" id="n" value="N" style="width: 30px; height: 30px" onclick="drive(8)" onmouseover="highlight(8)" onmouseout="dehighlight(8)" />
</td>
<td>
<input type="button" id="ne" value="NE" style="width: 30px; height: 30px" onclick="drive(9)" onmouseover="highlight(9)" onmouseout="dehighlight(9)" />
</td>
</tr>

<tr>
<td>
<input type="button" id="w" value="W" style="width: 30px; height: 30px" onclick="drive(4)" onmouseover="highlight(4)" onmouseout="dehighlight(4)" />
</td>
<td>
<input type="button" id="zero" value="0" style="width: 30px; height: 30px" onclick="drive(5)" onmouseover="highlight(5)" onmouseout="dehighlight(5)" />
</td>
<td>
<input type="button" id="e" value="E" style="width: 30px; height: 30px" onclick="drive(6)" onmouseover="highlight(6)" onmouseout="dehighlight(6)" />
</td>
</tr>

<tr>
<td>
<input type="button" id="sw" value="SW" style="width: 30px; height: 30px" onclick="drive(1)" onmouseover="highlight(1)" onmouseout="dehighlight(1)" />
</td>
<td>
<input type="button" id="s" value="S" style="width: 30px; height: 30px" onclick="drive(2)" onmouseover="highlight(2)" onmouseout="dehighlight(2)" />
</td>
<td>
<input type="button" id="se" value="SE" style="width: 30px; height: 30px" onclick="drive(3)" onmouseover="highlight(3)" onmouseout="dehighlight(3)" />
</td>
</tr>
</table>
<input type="button" id="generateTrack" value="Generate track" onclick="drawTrack(10, 100, 200)" />
<input type="button" id="clear" value="Clear screen" onclick="clearScreen()" />
</body>
</html>
